home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / TODO.PAK / TODOLIST.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  14KB  |  535 lines

  1. //---------------------------------------------------------------------
  2. //
  3. //  TODOLIST.CPP - part of TODO example program
  4. //
  5. //      Copyright (c) 1991, 1993 by Borland International
  6. //      All Rights Reserved.
  7. //
  8. //---------------------------------------------------------------------
  9.  
  10. #define STRICT
  11.  
  12. #include <services/wsysinc.h>
  13. #include <windowsx.h>
  14. #include <strstrea.h>
  15. #include <fstream.h>
  16. #include <ctype.h>
  17. #include <checks.h>
  18. #include <string.h>
  19.  
  20. #include "classlib\objstrm.h"
  21. #include "todolist.h"
  22. #include "tododefs.h"
  23. #include "tododlgs.h"
  24.  
  25. //---------------------------------------------------------------------
  26. //
  27. //  ostream& operator << ( ostream&, const TodoEntry& );
  28. //
  29. //  puts a TodoEntry onto an ostream in text form.
  30. //
  31. //---------------------------------------------------------------------
  32.  
  33. ostream& operator << ( ostream& os, const TodoEntry& tde )
  34. {
  35.     char temp[ 256 ];
  36.     ostrstream tstr( temp, sizeof temp );
  37.     tstr << tde.Priority
  38.          << '\t'
  39.          << tde.DateCreated
  40.          << '\t'
  41.          << tde.DateDue
  42.          << '\t'
  43.          << tde.Text
  44.          << ends;
  45.     return os << temp;
  46. }
  47.  
  48. //---------------------------------------------------------------------
  49. //
  50. //  ipstream& operator >> ( ipstream& is, TodoEntry& td );
  51. //  opstream& operator << ( opstream& os, TodoEntry& td );
  52. //
  53. //  inserter and extractor for TodoEntry and persistent streams.  
  54. //  These work together to write entries out to a persistent stream 
  55. //  and read them back in.
  56. //
  57. //---------------------------------------------------------------------
  58.  
  59. ipstream& operator >> ( ipstream& is, TodoEntry& td )
  60. {
  61.     is >> td.Priority >> td.DateDue >> td.DateCreated >> td.Text;
  62.     td.Dirty = FALSE;
  63.     return is;
  64. }
  65.  
  66. opstream& operator << ( opstream& os, const TodoEntry& td )
  67. {
  68.     os << td.Priority << td.DateDue << td.DateCreated << td.Text;
  69.     const_cast<TodoEntry&>(td).Dirty = FALSE;
  70.     return os;
  71. }
  72.  
  73. //---------------------------------------------------------------------
  74. //
  75. //  member functions for class TodoList.
  76. //
  77. //---------------------------------------------------------------------
  78.  
  79. void TodoList::Add( const TodoEntry& e )
  80. {
  81.     Dirty = TRUE;               // mark that the list has been modified
  82.     Vect.Add( e );              // add the entry
  83. }
  84.  
  85. void TodoList::Detach( unsigned idx )
  86. {
  87.     Dirty = TRUE;               // mark that the list has been modified
  88.     Vect.Detach( idx );         // remove the entry
  89. }
  90.  
  91. int TodoList::IndexOf( const TodoEntry& tde )
  92. {
  93.     for( int i = 0; i < Vect.Count(); i++ )
  94.         if( Vect[i] == tde )
  95.             return i;
  96.     return -1;
  97. }
  98.  
  99. static int CheckModified( const TodoEntry& ent, void * )
  100. {
  101.     return ent.Modified();
  102. }
  103.  
  104. BOOL TodoList::Modified() const
  105. {
  106.     if( Dirty == TRUE )         // if we've added or deleted entries
  107.         return TRUE;            // we've been modified
  108.                                 // otherwise, if any entry has been
  109.                                 // modified, the list has been modified.
  110.     else
  111.         return Vect.FirstThat( CheckModified, 0 ) != 0;
  112. }
  113.  
  114. static void MarkEntrySaved( TodoEntry& ent, void * )
  115. {
  116.     ent.Clear();
  117. }
  118.  
  119. void TodoList::MarkSaved() const
  120. {
  121.     const_cast<TodoList&>(*this).Dirty = FALSE;
  122.     const_cast<TodoList&>(*this).Vect.ForEach( MarkEntrySaved, 0 );
  123. }
  124.  
  125. void TodoList::Clear()
  126. {
  127.     Vect.Flush();
  128. }
  129.  
  130. ipstream& operator >> ( ipstream& is, TodoList& td )
  131. {
  132.     unsigned count;
  133.     is >> count;
  134.     while( count-- != 0 )
  135.         {
  136.         TodoEntry temp;
  137.         is >> temp;
  138.         if( !is )
  139.             return is;  // if stream isn't valid, don't try to add.
  140.         td.Add( temp );
  141.         }
  142.     td.MarkSaved();
  143.     return is;
  144. }
  145.  
  146. opstream& operator << ( opstream& os, const TodoList& td )
  147. {
  148.     os << td.Vect.Count();
  149.     TSVectorIteratorImp<TodoEntry> iter( td.Vect );
  150.     while( iter )
  151.         {
  152.         os << iter.Current();
  153.         iter++;
  154.         }
  155.     td.MarkSaved();
  156.     return os;
  157. }
  158.  
  159. //---------------------------------------------------------------------
  160. //
  161. //  const ListBox& ListBox::operator = ( const TodoList& tdl );
  162. //
  163. //  copies the contents of a TodoList into a ListBox.
  164. //
  165. //---------------------------------------------------------------------
  166.  
  167. const ListBox& ListBox::operator = ( const TodoList& tdl )
  168. {
  169.     PRECONDITION( hListBox != 0 );
  170.  
  171.     Clear();
  172.     TSVectorIteratorImp<TodoEntry> iter( tdl.Vect );
  173.     while( iter )
  174.         {
  175.         char buf[100];      // write the entry into a string
  176.                             // and insert that string into
  177.                             // the list box
  178.         ostrstream o(buf, 100);
  179.         o << iter.Current() << ends;
  180.         SendMessage( hListBox, LB_ADDSTRING, NULL, (LONG)(LPSTR)buf );
  181.         iter++;
  182.         }
  183.     Select( 0 );
  184.  
  185.     return *this;
  186. }
  187.  
  188. void ListBox::Insert( int i, const TodoEntry& tde )
  189. {
  190.     char temp[100];
  191.     ostrstream o(temp, sizeof(temp));
  192.     o << tde << ends;
  193.  
  194.     SendMessage( hListBox, LB_INSERTSTRING, i, (LONG)(LPSTR)temp );
  195.     Select( i );
  196. }
  197.  
  198. void ListBox::Create( HWND owner, HWND hInst, const RECT &wrect )
  199. {
  200.     hListBox = ::CreateWindow(
  201.         "ListBox", NULL,
  202.         LBS_NOTIFY | WS_BORDER | WS_VSCROLL |
  203.             LBS_USETABSTOPS | WS_CHILD | WS_VISIBLE,
  204.         wrect.left,
  205.         wrect.top,
  206.         wrect.right - wrect.left,
  207.         wrect.bottom - wrect.top,
  208.         (HWND)owner,
  209.         (HMENU)IDC_LISTBOX,
  210.         (HINSTANCE)hInst,
  211.         NULL );
  212.  
  213.     int tabs[] = { 10, 100, 200 };
  214.     SendMessage( hListBox,
  215.                  LB_SETTABSTOPS,
  216.                  sizeof(tabs)/sizeof(*tabs),
  217.                  (LONG)(LPSTR)tabs
  218.                 );
  219.     Focus();
  220. }
  221.  
  222. //---------------------------------------------------------------------
  223. //
  224. //  member functions for class TodoWindow.
  225. //
  226. //  these are mostly self-explanatory.
  227. //
  228. //---------------------------------------------------------------------
  229.  
  230. BOOL TodoWindow::RegisterClass()
  231. {
  232.     WNDCLASS wc;
  233.  
  234.     wc.style = 0;
  235.     wc.lpfnWndProc = Window::WndProc;
  236.     wc.cbClsExtra = 0;
  237.     wc.cbWndExtra = 0;
  238.     wc.hInstance =(HINSTANCE) hInst;
  239.     wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
  240.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  241.     wc.hbrBackground =(HBRUSH) GetStockObject( WHITE_BRUSH );
  242.     wc.lpszMenuName = "TodoMenu";
  243.     wc.lpszClassName = "TodoClass";
  244.  
  245.     return ::RegisterClass( &wc );
  246. }
  247.  
  248. BOOL TodoWindow::CreateNewWindow()
  249. {
  250.     hWindow = ::CreateWindow(
  251.         "TodoClass",
  252.         "Todo List",
  253.         WS_OVERLAPPEDWINDOW,
  254.         CW_USEDEFAULT,
  255.         CW_USEDEFAULT,
  256.         CW_USEDEFAULT,
  257.         CW_USEDEFAULT,
  258.         NULL,
  259.         NULL,
  260.         (HINSTANCE)hInst,
  261.         NULL
  262.         );
  263.     if( hWnd() == 0 )
  264.         return FALSE;
  265.  
  266.     Insert();                   // insert this window into the window list
  267.  
  268.     RECT wrect;
  269.     GetClientRect( (HWND)hWnd(), (LPRECT) &wrect);
  270.     LB.Create( (HWND)hWnd(), (HWND)hInst, wrect );
  271.                                 // build a list box in the client rectangle
  272.     LB = Tdl;                   // copy the Todo list into the list box
  273.  
  274.     ::ShowWindow( (HWND)hWnd(), Show );
  275.     ::UpdateWindow( (HWND)hWnd() );
  276.     return TRUE;
  277. }
  278.  
  279. void TodoWindow::ShowAboutBox()
  280. {
  281.     AboutBox ab( (HWND)hWnd() );
  282.     ab.Run();
  283. }
  284.  
  285. void TodoWindow::ShowEditBox()
  286. {
  287.     int cur = LB.Current();
  288.     if( cur == -1 )             // if there's nothing in the list,
  289.         NewEntry();             // need to create an entry
  290.     else
  291.         {
  292.         EditBox ed( (HWND)hWnd(), Tdl[cur] );
  293.         ed.Run();
  294.         LB.Replace( cur, Tdl[cur] );
  295.         }
  296. }
  297.  
  298. void TodoWindow::NewEntry()
  299. {
  300.     TodoEntry tde;
  301.     EditBox ed( (HWND)hWnd(), tde );
  302.  
  303.     if( ed.Run() == 0 )         // ed.Run() returns 0 if terminated by
  304.         {                       // OK, 1 if terminated by Cancel.
  305.         Tdl.Add( tde );
  306.         LB.Insert( Tdl.IndexOf( tde ), tde );
  307.         }
  308. }
  309.  
  310. void TodoWindow::DelEntry()
  311. {
  312.     int cur = LB.Current();
  313.     if( cur == -1 )             // if there's nothing in the list, there's
  314.         return;                 // nothing to delete.
  315.     Tdl.Detach( cur );
  316.     LB.Remove( cur );
  317.     LB.Select( cur );
  318. }
  319.  
  320. void TodoWindow::MoveListBox()
  321. {
  322.     RECT wrect;
  323.     GetClientRect( (HWND)hWnd(), (LPRECT) &wrect);
  324.  
  325.     LB.Move( wrect );
  326. }
  327.  
  328. //---------------------------------------------------------------------
  329. //
  330. //  void TodoWindow::CheckSave();
  331. //
  332. //  checks whether the Todo list has been modified.  If it has, asks
  333. //  the user whether to save the list or not, and if it is to be saved,
  334. //  writes it to a file.
  335. //
  336. //---------------------------------------------------------------------
  337.  
  338. void TodoWindow::CheckSave()
  339. {
  340.     if( Tdl.Modified() == TRUE && ShowSaveBox() == TRUE )
  341.         SaveFile();
  342. }
  343.  
  344. void TodoWindow::NewList()
  345. {
  346.     CheckSave();                // dump the current list
  347.     Tdl.Clear();
  348.     LB.Clear();
  349.     *FileName = '\0';           // mark that there's no file
  350.     *TitleName = '\0';
  351. }
  352.  
  353. void TodoWindow::OpenFile()
  354. {
  355.     CheckSave();                // dump the current list
  356.     Tdl.Clear();
  357.     LB.Clear();
  358.     if( FileBox::GetOpenFileName( hWnd(), FileName, TitleName ) == TRUE )
  359.         ReadFile();             // read new data from the specified file
  360. }
  361.  
  362. void TodoWindow::SaveFile()
  363. {
  364.     if( *TitleName == '\0' )
  365.         SaveFileAs();
  366.     else
  367.         WriteFile();
  368. }
  369.  
  370. void TodoWindow::SaveFileAs()
  371. {
  372.     if( FileBox::GetSaveFileName( hWnd(), FileName, TitleName ) == TRUE )
  373.         WriteFile();
  374. }
  375.  
  376. void TodoWindow::ReadFile()
  377. {
  378.     ifpstream in( FileName );           // open the input file
  379.     in >> Tdl;                          // read the Todo list
  380.     if( !in )                           // check whether read succeeded
  381.         throw( FileError( FileName ) );
  382.     LB = Tdl;                           // build the list box
  383. }
  384.  
  385. void TodoWindow::WriteFile()
  386. {
  387.     ofpstream out( FileName );
  388.     out << Tdl;
  389.     if( !out )                          // check whether write succeeded
  390.         throw( FileError( FileName ) );
  391. }
  392.  
  393. BOOL TodoWindow::ShowSaveBox()
  394. {
  395.     if( MessageBox( (HWND)hWnd(),
  396.         "Save Changes",
  397.         "Current List Modified",
  398.         MB_YESNO | MB_ICONQUESTION ) == IDYES )
  399.         return TRUE;
  400.     else
  401.         return FALSE;
  402. }
  403.  
  404. //---------------------------------------------------------------------
  405. //
  406. //  BOOL TodoWindow::ProcessCommand( WPARAM wParam, LPARAM lParam );
  407. //
  408. //  dispatches commands to the appropriate member functions.
  409. //
  410. //---------------------------------------------------------------------
  411.  
  412. BOOL TodoWindow::ProcessCommand( WPARAM wParam, LPARAM lParam )
  413. {
  414.     switch( GET_WM_COMMAND_ID(wParam, lParam) )
  415.         {
  416.  
  417.         case IDM_QUIT:
  418.             SendMessage((HWND)hWnd(), WM_CLOSE, 0, 0L);
  419.             return TRUE;
  420.  
  421.         case IDM_NEW_LIST:
  422.             NewList();
  423.             return TRUE;
  424.  
  425.         case IDM_OPEN:
  426.             OpenFile();
  427.             return TRUE;
  428.  
  429.         case IDM_SAVE:
  430.             SaveFile();
  431.             return TRUE;
  432.  
  433.         case IDM_SAVEAS:
  434.             SaveFileAs();
  435.             return TRUE;
  436.  
  437.         case IDM_EDIT:
  438.             ShowEditBox();
  439.             return TRUE;
  440.  
  441.         case IDM_NEW_ENTRY:
  442.             NewEntry();
  443.             return TRUE;
  444.  
  445.         case IDM_DEL_ENTRY:
  446.             DelEntry();
  447.             return TRUE;
  448.  
  449.         case IDM_ABOUT:
  450.             ShowAboutBox();
  451.             return TRUE;
  452.  
  453.         case IDC_LISTBOX:
  454.             if( GET_WM_COMMAND_CMD( wParam, lParam ) == LBN_DBLCLK )
  455.                 {
  456.                 ShowEditBox();
  457.                 return TRUE;
  458.                 }
  459.             else
  460.                 return FALSE;
  461.         default:
  462.             return FALSE;
  463.         }
  464. }
  465.  
  466. //---------------------------------------------------------------------
  467. //
  468. //  LONG TodoWindow::Dispatch( UINT msg, WPARAM wParam, LPARAM lParam );
  469. //
  470. //  dispatches messages to the appropriate member functions.
  471. //
  472. //---------------------------------------------------------------------
  473.  
  474. LONG TodoWindow::Dispatch( UINT msg, WPARAM wParam, LPARAM lParam )
  475. {
  476.     switch( msg )
  477.         {
  478.         case WM_COMMAND:
  479.  
  480.             if( ProcessCommand( wParam, lParam ) == TRUE )
  481.                 {
  482.                 LB.Focus();
  483.                 return 0;
  484.                 }
  485.             break;
  486.  
  487.         case WM_MOVE:
  488.         case WM_SIZE:
  489.  
  490.             MoveListBox();
  491.             return 0;
  492.  
  493.         case WM_QUERYENDSESSION:
  494.             return TRUE;
  495.  
  496.         case WM_CLOSE:
  497.  
  498.             CheckSave();
  499.             DestroyWindow( (HWND)hWnd() );
  500.             return 0;
  501.  
  502.         case WM_DESTROY:
  503.         case WM_QUIT:
  504.  
  505.             PostQuitMessage( 0 );
  506.             break;
  507.         }
  508.  
  509.     return Window::Dispatch( msg, wParam, lParam );
  510. }
  511.  
  512. //---------------------------------------------------------------------
  513. //
  514. //  int PASCAL WinMain( HINSTANCE, HINSTANCE, LPSTR, int );
  515. //
  516. //  the main entry point for the program.
  517. //
  518. //---------------------------------------------------------------------
  519.  
  520. int PASCAL WinMain( HINSTANCE hInstance,
  521.                     HINSTANCE hPrevInstance,
  522.                     LPSTR     lpCmd,
  523.                     int       nShow)
  524. {
  525.     WinBase::hInst = hInstance;
  526.     WinBase::hPrevInst = hPrevInstance;
  527.     WinBase::Cmd = lpCmd;
  528.     WinBase::Show = nShow;
  529.  
  530.     TodoWindow td;
  531.     td.Create();
  532.     return td.Run();
  533. }
  534.  
  535.